import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class DropMenuContainer extends StatefulWidget {
  final Widget child;
  final Color? coverColor;
  DropMenuController controller;
  final bool isBottomOut;
  final int duration;

  DropMenuContainer(
      {super.key,
      required this.child,
      required this.controller,
      this.coverColor,
        this.duration = 200,
      this.isBottomOut = false});

  @override
  State<StatefulWidget> createState() => _DropMenuContainerState();
}

class _DropMenuContainerState extends State<DropMenuContainer>
    with SingleTickerProviderStateMixin {
  int status = 0;

  late AnimationController controller;
  late Animation<Offset> animation;

  var showDrop = false;


  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        duration: Duration(milliseconds: widget.duration), vsync: this); //两秒的时间完成该动画

    if(widget.isBottomOut){
      animation = Tween(begin: const Offset(0, 1), end: const Offset(0, 0))
          .animate(controller); //这个设置就是向下移动
    }else{
      animation = Tween(begin: const Offset(0, -1), end: const Offset(0, 0))
          .animate(controller); //这个设置就是向下移动
    }

    try{
      widget.controller.streamController?.stream.listen((event) {
        setState(() {
          status = event;
        });
        if (event == 1) {
          controller.forward();
        } else {
          controller.animateBack(0, duration: Duration(milliseconds: widget.duration));
        }
        
      });
    }catch(e){
      
    }

    controller.addStatusListener((status) {
      if (status == AnimationStatus.forward) {
        setState(() {
          showDrop = true;
        });
      }
      if (status == AnimationStatus.dismissed) {
        setState(() {
          showDrop = false;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return StatefulBuilder(builder: (context, setState) {
      return Stack(
        clipBehavior: Clip.antiAlias,
        children: [
          Positioned(
            left: 0,
            right: 0,
            top: 0,
            bottom: 0,
            child: widget.child,
          ),
          if (showDrop && widget.controller.dropWidget != null)
            Positioned(
              left: 0,
              right: 0,
              top: 0,
              bottom: 0,
              child: Stack(
                children: [
                  Positioned(
                    left: 0,
                    right: 0,
                    top: -10,
                    bottom: -10,
                    child: GestureDetector(
                      child: Container(
                        color: widget.coverColor ?? Colors.black.withAlpha(80),
                      ),
                      onTap: () {
                        widget.controller.hide(isTouchDismiss: true);
                      },
                    ),
                  ),
                  widget.isBottomOut
                      ? Positioned(
                          left: 0,
                          bottom: 0,
                          right: 0,
                          child: SlideTransition(
                            position: animation,
                            child: widget.controller.dropWidget!,
                          ),
                        )
                      : Positioned(
                          left: 0,
                          top: 0,
                          right: 0,
                          child: SlideTransition(
                            position: animation,
                            child: widget.controller.dropWidget!,
                          ),
                        )
                ],
              ),
            ),
        ],
      );
    });
  }
}

class DropMenuController {
  DropMenuController({this.dropWidget}) {
    streamController ??= StreamController();
  }

  Widget? dropWidget;

  StreamController<int>? streamController;
  var status = 0;

  bool get isShow => status == 1;

  Function(bool isShow,bool isTouchDismiss)? onShowHideListener;

  void showDropMenu({Widget? menuWidget}) {
    if (menuWidget != null) {
      dropWidget = menuWidget;
    }
    streamController?.sink.add(1);
    status = 1;
    onShowHideListener?.call(true,false);
  }

  void hide({bool isTouchDismiss = false}) {
    streamController?.sink.add(0);
    status = 0;
    onShowHideListener?.call(false,isTouchDismiss);
  }

  void release() {
    onShowHideListener = null;
    streamController?.sink.close();
    streamController = null;
  }
}
